On Windows 11, in File Explorer, gtk-picture.exe
has Windows’ default icon for an executable file and GTK4’s default icon in the task bar when running:
I wanted to customise these icons. Also, I wanted a similar icon to appear in the application’s window’s header bar, to the left.
*.res file
The icon can be set by linking an appropriate *.res
(resource) file. In my case, the file was haskell-logo.res
. The file is linked by specifying the GHC option -optl
. For example:
1 2 3 4 5 6 7 8 9 10 11 |
executables: gtk-picture: main: Main.hs source-dirs: app generated-other-modules: Paths_gtk_picture ghc-options: - -threaded - -rtsopts - -with-rtsopts=-N - -optl-mwindows - -optl=haskell-logo.res |
*.rc file
A *.res
file is created by compiling an appropriate *.rc
(resource script) file with the windres
application. That application is provided by the MSYS2 package mingw-w64-x86_64-binutils
. It acts like the Windows Resource Compiler. For example:
1 |
stack exec -- windres --input haskell-logo.rc --output-format coff --output haskell-logo.res |
The *.rc
file specifies the icon. For example:
1 |
IDI_ICON1 ICON "haskell-logo.ico" |
IDI_ICON1
is an identifier for the resource. By convention, the initial IDI
indicates that the resource is an icon or bitmap. ICON
identifies the resource type as an icon. The type is followed by the path to the resource, in this case a *.ico
(Windows icon) file.
*.ico file
An *.ico
file stores one or more icon images of different sizes. It can be created from a *.svg
file with the ImageMagick application. For example:
1 |
magick -background none haskell-logo.svg -define icon:auto-resize haskell-logo.ico |
It is important to specify -background none
before the input *.svg
file is specified, otherwise the background will be white.
I used the 2009 Thompson-Wheeler logo, resized in InkScape to be 256 px x 256 px:
gtk-picture.exe
The end result was as desired: in File Explorer, gtk-picture.exe
had the specified icon and the same icon in the task bar when running:
For an icon in the application’s header bar, the solution was for the ApplicationWindow
value to specify a HeaderBar
value as its titleBar
and for an appropriate Image
value to be packed at the start of that header bar, as follows:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
activate :: Gtk.Application -> IO () activate app = do ... image <- iconImage headerBar <- new Gtk.HeaderBar [] #packStart headerBar image window <- new Gtk.ApplicationWindow [ #application := app , #title := "Clicking on a picture" , #titlebar := headerBar , #child := grid ] window.show iconFile :: IO FilePath iconFile = getDataFileName "haskell-logo24x24.png" iconImage :: IO Gtk.Image iconImage = iconFile >>= Gtk.imageNewFromFile |
A 24 px square image seemed an appropriate size. If the titleWidget
of a HeaderBar
is not set, it displays the title of the window that it is contained in. The default showTitleButtons
of a HeaderBar
is True
.